package mdt.model;

import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.List;

import org.tigris.gef.base.Editor;
import org.tigris.gef.base.FigModifyingModeImpl;
import org.tigris.gef.base.PathItemPlacementStrategy;
import org.tigris.gef.presentation.Fig;
import org.tigris.gef.presentation.FigEdge;

public class ModeLabelDrag extends FigModifyingModeImpl {
  
  /**
   * The text label that is currently being dragged, or
   * null if nothing is being dragged.
   */
  private Fig dragFig = null;
  
  /**
   * The FigEdge that contains the label that is currently
   * being dragged.  We have to keep track of this because
   * the FigEdge is the only object that holds references to the
   * PathItems that place it's child figs.  The child Figs do not
   * have these references. 
   * figEdge = null if nothing is being dragged.
   */
  private FigEdge figEdge = null;
  
  /**
   * Point for tracking a mouse drag, indicates the last recorded mouse 
   * point.  When a new mouse drag event occurs, the difference between
   * the current point and dragBasePoint is the delta in position.
   */
  private Point dragBasePoint = new Point(0, 0);
 
  /**
   * X-offset for storing the location of the mouse click on a label
   * relative to the centre of the label.  Used while dragging to 
   * ensure that the user can click anywhere to start the drag, and things
   * still behave sensibly.  X component.
   */
  private int deltax = 0;
  
  /**
   * Y-offset for storing the location of the mouse click on a label
   * relative to the centre of the label.  Used while dragging to 
   * ensure that the user can click anywhere to start the drag, and things
   * still behave sensibly.  X component.
   */
  private int deltay = 0;
  
  /**
   * Constructor for creating the ModeLabelDrag instance.
   * @param editor The editor which will own this mode.
   */
  public ModeLabelDrag(Editor editor) {
      super(editor);
  }
  
  /**
   * Constructor for creating the ModeLabelDrag instance.
   */
  public ModeLabelDrag() {
      super();
  }

  /** 
   * Reply a string of instructions that should be shown in the
   * statusbar when this mode starts.
   * @return The text to display in the status bar.
   * @override 
   */
  public String instructions() {
      return "  ";
  }
  /**
   * Grabs label to begin movement. Turns cursor into a hand.
   * @param me The mouse event to process.
   * @override
   * @see org.tigris.gef.base.ModeImpl#mousePressed(java.awt.event.MouseEvent)
   */
  public void mousePressed(MouseEvent me) {
      Point clickPoint = me.getPoint(); 
      Fig underMouse = editor.hit(clickPoint);
      if (underMouse instanceof FigEdge) {
          List<Fig> figList = ((FigEdge) underMouse).getPathItemFigs();
          for (Fig fig : figList) {
              if (fig.contains(clickPoint)) {
                  // Consume to stop other modes from trying to take over
                  me.consume();
                  dragFig = fig;
                  dragBasePoint = fig.getCenter();
                  deltax = clickPoint.x - dragBasePoint.x;
                  deltay = clickPoint.y - dragBasePoint.y;
                  figEdge = (FigEdge) underMouse;
                  break;
              }
          }
      }
  }
  
  /**
   * Handle mouseReleased events.
   * @param me The mouse event to process.
   * @see org.tigris.gef.base.ModeImpl#mouseReleased(java.awt.event.MouseEvent)
   */
  public void mouseReleased(MouseEvent me) {
      if (dragFig != null) {
          dragFig = null;
      }
  }
  
  /**
   * Handle mouseDragged events.
   * @param me The mouse event to process.
   * @see org.tigris.gef.base.ModeImpl#mouseDragged(java.awt.event.MouseEvent)
   */
  public void mouseDragged(MouseEvent me) {
      if (dragFig != null) {
          me = editor.translateMouseEvent(me);
          Point newPoint = me.getPoint();
          // Subtract the the offset of the click, to take account of user
          // having not initially clicked in the centre.
          newPoint.translate(-deltax, -deltay);
          PathItemPlacementStrategy pips 
              = figEdge.getPathItemPlacementStrategy(dragFig);
          pips.setPoint(newPoint);
          newPoint = pips.getPoint();
          int dx = newPoint.x - dragBasePoint.x;
          int dy = newPoint.y - dragBasePoint.y;
          dragBasePoint.setLocation(newPoint);
          dragFig.translate(dx, dy);
          me.consume();
          editor.damaged(dragFig);
      }
  }

}

